import os
import re
import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import ttk


class BibRefOrganizer:
    def __init__(self, root):
        self.root = root
        self.root.title("文献引用整理工具 (BibRef Organizer)")
        self.root.geometry("800x600")

        # 设置样式
        style = ttk.Style()
        style.configure("TButton", padding=6, relief="flat", background="#ccc")

        # 主框架
        main_frame = ttk.Frame(root, padding=10)
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 文件夹选择区域
        folder_frame = ttk.LabelFrame(main_frame, text="选择文件夹", padding=10)
        folder_frame.pack(fill=tk.X, padx=5, pady=5)

        self.folder_path = tk.StringVar()
        folder_entry = ttk.Entry(folder_frame, textvariable=self.folder_path, width=60)
        folder_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)

        browse_button = ttk.Button(folder_frame, text="浏览...", command=self.browse_folder)
        browse_button.pack(side=tk.RIGHT, padx=5)

        # 操作按钮
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill=tk.X, pady=10)

        process_button = ttk.Button(button_frame, text="整理引用文献", command=self.process_files)
        process_button.pack(side=tk.LEFT, padx=5)

        help_button = ttk.Button(button_frame, text="帮助", command=self.show_help)
        help_button.pack(side=tk.RIGHT, padx=5)

        # 日志区域
        log_frame = ttk.LabelFrame(main_frame, text="处理日志", padding=10)
        log_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

        self.log_text = tk.Text(log_frame, wrap=tk.WORD, width=80, height=20)
        self.log_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        scrollbar = ttk.Scrollbar(log_frame, orient=tk.VERTICAL, command=self.log_text.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.log_text.configure(yscrollcommand=scrollbar.set)

        # 状态栏
        self.status_var = tk.StringVar()
        self.status_var.set("就绪")
        status_bar = ttk.Label(root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
        status_bar.pack(side=tk.BOTTOM, fill=tk.X)

        # 初始日志
        self.log("欢迎使用文献引用整理工具 👋")
        self.log("请选择包含TEX文件的文件夹进行处理")

    def browse_folder(self):
        folder_selected = filedialog.askdirectory(title="选择包含TEX文件的文件夹")
        if folder_selected:
            self.folder_path.set(folder_selected)
            self.log(f"已选择文件夹: {folder_selected}")
            self.status_var.set(f"已选择: {folder_selected}")

    def log(self, message):
        self.log_text.insert(tk.END, message + "\n")
        self.log_text.see(tk.END)
        self.root.update_idletasks()

    def show_help(self):
        help_text = """文献引用整理工具使用说明:

1. 点击"浏览..."按钮选择包含TEX文件的文件夹
2. 文件夹中应包含1.tex, 2.tex, 3.tex, 4.tex和reference.tex文件
3. 点击"整理引用文献"按钮开始处理
4. 程序将提取所有文件中的引用，并按引用顺序重新排列参考文献
5. 未被引用的条目将被注释并放置在文件末尾
6. 处理完成后，您可以选择覆盖原文件或保存为新文件

注意: 建议在处理前备份您的reference.tex文件"""

        help_window = tk.Toplevel(self.root)
        help_window.title("帮助")
        help_window.geometry("600x400")
        help_window.transient(self.root)
        help_window.grab_set()

        text = tk.Text(help_window, wrap=tk.WORD, padx=10, pady=10)
        text.pack(fill=tk.BOTH, expand=True)
        text.insert(tk.END, help_text)
        text.config(state=tk.DISABLED)

        close_button = ttk.Button(help_window, text="关闭", command=help_window.destroy)
        close_button.pack(pady=10)

    def process_files(self):
        folder_path = self.folder_path.get()

        if not folder_path:
            messagebox.showerror("错误", "请先选择文件夹")
            return

        self.log("开始处理文件...")
        self.status_var.set("处理中...")

        try:
            # 读取TEX文件并提取引用
            bib_id_list = []
            bib_id_order = {}  # 记录每个引用首次出现的位置
            self.log("正在读取TEX文件并提取引用...")

            citation_count = 0
            for i in range(1, 5):
                file_path = os.path.join(folder_path, f"{i}.tex")
                if os.path.exists(file_path):
                    with open(file_path, 'r', encoding='utf-8', errors='replace') as file:
                        content = file.read()
                        citations = re.findall(r'\\cite\{([^}]+)\}', content)
                        for citation in citations:
                            citation_count += 1
                            # 处理多个引用（以逗号分隔）
                            ids = [cid.strip() for cid in citation.split(',')]
                            for bib_id in ids:
                                if bib_id not in bib_id_list:
                                    bib_id_list.append(bib_id)
                                    bib_id_order[bib_id] = len(bib_id_order)  # 记录首次出现位置
                    self.log(f"已处理 {i}.tex, 找到 {len(citations)} 个引用标签。")
                else:
                    self.log(f"警告: 未找到 {i}.tex 文件。")

            self.log(f"总共发现 {citation_count} 个引用标签，包含 {len(bib_id_list)} 个不同的引用ID。")

            # 读取reference.tex
            reference_path = os.path.join(folder_path, "reference.tex")
            if not os.path.exists(reference_path):
                messagebox.showerror("错误", "未在选择的文件夹中找到reference.tex文件。")
                self.status_var.set("处理失败")
                return

            with open(reference_path, 'r', encoding='utf-8', errors='replace') as file:
                reference_content = file.read()

            # 提取文件头部
            header_match = re.search(r'(.*?)\\begin\{thebibliography\}\{200\}', reference_content, re.DOTALL)
            header = header_match.group(1) if header_match else ""

            # 提取文献条目设置
            settings_match = re.search(r'\\begin\{thebibliography\}\{200\}(.*?)(?=\\bibitem)', reference_content,
                                       re.DOTALL)
            settings = settings_match.group(1) if settings_match else ""

            # 提取所有bibitem
            bibitem_pattern = r'\\bibitem\{([^}]+)\}(.*?)(?=\\bibitem\{|\\end\{thebibliography\})'
            bibitems = re.findall(bibitem_pattern, reference_content, re.DOTALL)

            # 检查是否所有引用的ID都在参考文献中
            reference_ids = [item[0] for item in bibitems]
            missing_ids = [bid for bid in bib_id_list if bid not in reference_ids]

            if missing_ids:
                missing_list = ", ".join(missing_ids)
                messagebox.showwarning("缺少参考文献",
                                       f"以下被引用的文献ID在reference.tex中未找到:\n{missing_list}")
                self.log(f"警告: 以下被引用的文献ID在reference.tex中未找到: {missing_list}")

            # 区分使用和未使用的参考文献
            used_bibitems = []
            unused_bibitems = []

            for bib_id, content in bibitems:
                if bib_id in bib_id_list:
                    used_bibitems.append((bib_id, content))
                else:
                    unused_bibitems.append((bib_id, content))

            # 根据引用顺序排序文献条目
            used_bibitems.sort(key=lambda x: bib_id_order.get(x[0], 999))

            # 创建新的参考文献内容
            new_reference_content = header + "\\begin{thebibliography}{200}" + settings

            # 添加已使用的文献条目
            for bib_id, content in used_bibitems:
                new_reference_content += f"\\bibitem{{{bib_id}}}{content}"

            new_reference_content += "\\end{thebibliography}\n\\clearpage\n\n"

            # 添加未使用的文献条目（注释）
            if unused_bibitems:
                new_reference_content += "%% 以下是未引用的条目\n%% 未引用\n"
                for bib_id, content in unused_bibitems:
                    content_lines = content.strip().split('\n')
                    commented_content = '%\n' + '\n'.join([f'%\t{line}' for line in content_lines]) + '\n%\n\n'
                    new_reference_content += f"%\\bibitem{{{bib_id}}}\n{commented_content}"

            # 询问用户保存位置
            save_choice = messagebox.askyesnocancel("保存选项",
                                                    "是否覆盖原始reference.tex文件？\n\n"
                                                    "● 是: 覆盖原文件\n"
                                                    "● 否: 保存为新文件\n"
                                                    "● 取消: 终止操作")

            if save_choice is None:  # 用户取消
                self.log("操作已被用户取消。")
                self.status_var.set("操作已取消")
                return

            if save_choice:  # 覆盖原文件
                output_path = reference_path
            else:  # 保存为新文件
                output_path = filedialog.asksaveasfilename(
                    defaultextension=".tex",
                    filetypes=[("TeX文件", "*.tex"), ("所有文件", "*.*")],
                    initialdir=folder_path,
                    initialfile="reference_sorted.tex",
                    title="保存整理后的参考文献文件"
                )
                if not output_path:
                    self.log("保存操作已被用户取消。")
                    self.status_var.set("保存已取消")
                    return

            with open(output_path, 'w', encoding='utf-8') as file:
                file.write(new_reference_content)

            self.log(f"成功保存至 {output_path}")
            self.log(f"共处理 {len(used_bibitems)} 个使用的参考文献和 {len(unused_bibitems)} 个未使用的参考文献。")

            self.status_var.set("处理完成")
            messagebox.showinfo("成功", "参考文献整理成功！")

        except Exception as e:
            self.log(f"错误: {str(e)}")
            self.status_var.set("处理失败")
            messagebox.showerror("错误", f"发生错误: {str(e)}")


if __name__ == "__main__":
    root = tk.Tk()
    app = BibRefOrganizer(root)
    root.mainloop()
